/*-
 * Copyright (c) 2007 Microsoft
 * All rights reserved.
 */

#include "StdAfx.h"
#include "mpicore.h"
#include "Comm.h"
#include "MPIException.h"
#include "AsyncResult.h"

using namespace Microsoft::ComputeCluster::MpiNet;

///<summary>
///Initialize MPI using the parameter
///</summary>
///<param name="param">The arguments passed from command line</param>
bool Core::Initialize(array<String ^> ^param)
{
    if (IsInitialized)
    {
        throw gcnew System::InvalidOperationException();
    }

    int paramCount = param->Length;
    char** buf = NULL;

    try
    {
        if (param->Length > 0)
        {
            buf = new char*[param->Length];
            for(int i = 0; i < paramCount; i++)
            {
                buf[i] = NULL;
                String^ str = (String^)param->GetValue(i);
                buf[i] = (char*)Marshal::StringToHGlobalAnsi(str).ToPointer();
            }
        }

        if (MPI_Init(&paramCount, &buf) == 0)
        {
            IsInitialized = true;
            Comm::World = gcnew Comm(MPI_COMM_WORLD);
            Comm::Self = gcnew Comm(MPI_COMM_SELF);
        }
    }
    finally
    {
        if (buf != NULL)
        {
            for(int i = 0; i < paramCount; i++)
            {
                if (buf[i] == NULL)
                    break;
                Marshal::FreeHGlobal(IntPtr(buf[i]));
            }

            delete[] buf;
        }
    }
    return IsInitialized;
}

///<summary>
///Shutdown MPI
///</summary>
void Core::Shutdown()
{
    MPI_Finalize();
}

///<summary>
///Get the current hostname
///</summary>
String^ Core::ProcessorName::get()
{
    char hostname[MPI_MAX_PROCESSOR_NAME];
    int hostnameLen;
    int ret = ::MPI_Get_processor_name( hostname, &hostnameLen );
    if (ret != MPI_SUCCESS)
        throw gcnew MPIException(ret);

    return gcnew String(hostname);
}

///<summary>
///Get world time
///</summary>
double Core::Wtime::get()
{
    return MPI_Wtime();
}

///<summary>
///Get world ticket
///</summary>
double Core::Wtick::get()
{
    return MPI_Wtick();
}
